package cz.spock.cms.service;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import cz.spock.cms.template.DatastoreTemplateLoader;
import cz.spock.core.service.BaseService;
import freemarker.ext.dom.NodeModel;
import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * this service should provide methods for freemarker template engine
 * @author miso
 *
 */
@Service
public class FreeMarkerService extends BaseService {
    
    private Configuration cfg;
    @Autowired
    private DatastoreTemplateLoader loader;
    
    // try configure custom template loader here
    public FreeMarkerService() {
        cfg = new Configuration();
    }
    
    
    public Template findTemplateByName(String name) {
        if((cfg.getTemplateLoader() == null) || !(cfg.getTemplateLoader() instanceof DatastoreTemplateLoader)) {
            if(loader == null) {
                // TODO fatal error, probably restart of server required
                System.out.println("LOADER IS STILL NULL");
                return null;
            }
            cfg.setTemplateLoader(loader);
        }
            
        if(name == null) {
            return null;
        }
        Template t = null;
        try {
            t = cfg.getTemplate(name);
        } catch (IOException e) {
            // TODO problem loading template
            System.out.println("error in findTemplateByName method in freeMarkerService: " + e.getMessage());
        }
        return t;
    }
    
    /**
     * creates xml document prepared for data input
     * 
     * @param template
     * @return
     */
    public File createXmlFromTemplate(String template) {
        if(template == null) {
            
        }
        
        DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
        Document doc = null;
        try {
            doc = fact.newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if(doc == null ) {
            
        }
        List<String> vars = this.parseTemplate(template);
        for(String var : vars) {
            NodeList nodes = doc.getElementsByTagName(var);
            if(nodes.getLength() != 0) { 
                nodes.item(0).getParentNode().appendChild(newChild);
            }
        }
        
        
        // TODO xml creating probably via DOM
        
        return null;
    }
    
    public Map<String, Object> createDataTreeFromXml(File xml) {               
        // check file
        if(!xml.exists()) {
            
        }
        if(!xml.canRead()) {
            
        }
        if(!xml.isFile()) {
            
        }
        
        HashMap<String, Object> map = new HashMap<String, Object>();
        try {
            map.put("doc", NodeModel.parse(xml, true, true));
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return map;
    }
    
    /**
     * returns list of freemarker variables found in given file
     * 
     * finds all ${something} in given string
     * 
     * @param template
     * @return
     */
    private List<String> parseTemplate(String template) {
        ArrayList<String> list = new ArrayList<String>();
        Pattern p = Pattern.compile("\\$\\{[^}]*\\}");
        Matcher m = p.matcher(template);
        int curPos = 0;
        while(m.find(curPos)) {
            int start = m.start();
            int end = m.end();
            curPos = end;
            list.add(template.substring(start, end));
        }
        return list;
    }
    
    /**
     * wrapper for testing purposes only
     * 
     * TODO delete thid method after testing
     * 
     * @param t
     * @return
     */
    public List<String> parse(String t) {
        return this.parseTemplate(t);
    }    
    
}
